package cc.owoo.godpen.thread;

import java.util.concurrent.CountDownLatch;

/**
 * 异步任务线程
 * Created by nimensei
 * 2022-03-31 上午 01:58
 **/
public class AsyncThreadPool {
    public static final Runnable NULL = () -> {
    };// 不执行任何内容

    private final Object lock = new Object();//线程锁
    private int count;// 最大线程数
    private int now;//当前线程数

    private OnLaunch onLaunch;// 启动回调函数
    private Runnable finish;// 结束回调函数
    private boolean isRun;// 是否正在运行

    public AsyncThreadPool(int count) {
        setMaxCount(count);
    }

    /**
     * 设置最大线程数
     *
     * @param count 最大线程数
     */
    public void setMaxCount(int count) {
        if (count <= 0)
            throw new IllegalArgumentException("线程数不能小于1：" + count);
        this.count = count;
    }

    /**
     * 获取最大线程数
     *
     * @return 最大线程数
     */
    public int getMaxCount() {
        return count;
    }

    /**
     * 获取当前线程池数量
     *
     * @return 当前线程池数量
     */
    public int getNowCount() {
        return now;
    }

    /**
     * 开始运行
     */
    public void start() {
        synchronized (lock) {
            if (isRun)
                return;
            isRun = true;
        }
        execute();
    }

    /**
     * 停止
     */
    public void stop() {
        synchronized (lock) {
            if (!isRun)
                return;
            isRun = false;
            if (now == 0)
                finish();
        }
    }

    /**
     * 设置启动回调函数
     *
     * @param onLaunch 启动回调函数
     */
    public void setOnLaunch(OnLaunch onLaunch) {
        synchronized (lock) {
            this.onLaunch = onLaunch;
        }
    }

    /**
     * 执行一个线程
     */
    private void execute() {
        synchronized (lock) {
            if (!isRun) {
                if (now == 0)
                    finish();
                return;
            }
            if (onLaunch == null)
                return;
        }
        while (true) {
            Runnable runnable;
            synchronized (lock) {
                if (now >= count)
                    break;
                runnable = onLaunch.launch();
                if (runnable == null) {
                    stop();
                    return;
                }
                if (runnable == NULL)
                    continue;
                ++now;
            }
            Threads.run(() -> {
                runnable.run();
                synchronized (lock) {
                    --now;
                }
                execute();
            });
        }
    }

    /**
     * 设置结束回调函数
     *
     * @param finish 结束回调函数
     */
    public void setOnFinish(Runnable finish) {
        this.finish = finish;
        if (!isRun)
            finish.run();
    }

    /**
     * 线程池已运行完成
     */
    private void finish() {
        Runnable runnable = finish;
        if (runnable == null)
            return;
        runnable.run();
    }

    /**
     * 等待所有任务完成
     */
    public void awaitFinish() {
        Runnable finish = this.finish;
        CountDownLatch countDownLatch = new CountDownLatch(1);
        setOnFinish(countDownLatch::countDown);
        try {
            countDownLatch.await();
        } catch (InterruptedException ignored) {
        }
        if (finish != null)
            finish.run();
    }

    /**
     * 启动回调函数
     */
    public interface OnLaunch {
        Runnable launch();
    }
}
